﻿using Chenxi;
using System;
using System.IO;
using System.Windows.Forms;
using System.Text.RegularExpressions;

namespace osuStd2Key
{
    public partial class MainForm : Form
    {
        public delegate void LogDelegate(string str);
        public LogDelegate Log;
        public delegate void ConvertDelegate(IConverter c);
        public delegate void ConvertStatusChanged(bool converting);
        public ConvertStatusChanged ConvertStatusCallback;
        public MainForm()
        {
            InitializeComponent();

            ConverterUIUtil.InitUI(this, LabelConverterName, LabelVersionName);

            OpenFromFileDialog.Filter = "osu谱面 (*.osu)|*.osu";
            SaveToFileDialog.Filter = "key谱面 (*.key)|*.key";
            ConverterUIUtil.BindFileSelect(ButtonSelectFromFile, TextConvertFromFile, OpenFromFileDialog, AutoGenerateSaveFilePath);
            ConverterUIUtil.BindFileSelect(ButtonSelectToFile, TextConvertToFile, SaveToFileDialog);
            ConverterUIUtil.BindFileDrag(TextConvertFromFile, AutoGenerateSaveFilePath);
            ConverterUIUtil.BindFileDrag(TextConvertToFile);

            CheckShowLog_CheckedChanged(null, null);

            Log = new LogDelegate(DoLog);
            ConvertStatusCallback = new ConvertStatusChanged(DoConvertStatusChange);
        }
        private void AutoGenerateSaveFilePath(string filePath)
        {
            string fileName = Path.GetFileName(filePath).ToLower();
            int diff = 0;
            if (fileName.Contains("[easy]")) diff = 1;
            else if (fileName.Contains("[normal]")) diff = 2;
            else if (fileName.Contains("[hard]")) diff = 3;
            else
            {
                AutoGenerateSaveFilePathV2(filePath);
                return;
            }
            Regex re = new Regex(@"^([\d]+)");
            if (!re.IsMatch(fileName))
            {
                AutoGenerateSaveFilePathV2(filePath);
                return;
            }
            GenerateSaveFilePathByInfo(Path.GetDirectoryName(filePath), re.Match(fileName).Groups[1].Value, diff);
        }
        private void AutoGenerateSaveFilePathV2(string filePath)
        {
            try
            {
                osuNote osu = new osuNote(File.ReadAllText(filePath));
                int diff = 0;
                switch (osu.Version.ToLower())
                {
                    case "easy": diff = 1; break;
                    case "normal": diff = 2; break;
                    case "hard": diff = 3; break;
                }
                if (diff == 0) return;
                GenerateSaveFilePathByInfo(Path.GetDirectoryName(filePath), osu.Artist, diff);
            }
            catch (Exception e)
            {
                ShowLog("Exception", e.ToString());
            }
        }
        private void GenerateSaveFilePathByInfo(string dir, string id, int diff)
        {
            TextConvertToFile.Text = Path.Combine(dir, "DJ5" + diff + id + ".key");
        }
        private void DoLog(string msg)
        {
            TextLog.AppendText(msg);
        }
        private void DoConvertStatusChange(bool converting)
        {
            if (converting)
            {
                ButtonConvert.Text = "转换中…";
                ButtonConvert.Enabled = false;
            }
            else
            {
                ButtonConvert.Text = "转换";
                ButtonConvert.Enabled = true;
            }
        }
        private void ConvertStatusChange(bool converting)
        {
            if (ButtonConvert.InvokeRequired)
            {
                BeginInvoke(ConvertStatusCallback, converting);
            }
            else
            {
                ConvertStatusCallback(converting);
            }
        }
        public void ShowLog(string tag, string msg)
        {
            ShowLogln(string.Format("[{0}] {1}", tag, msg));
        }
        public void ShowLogln(string msg)
        {
            ShowLog(msg + "\r\n");
        }
        public void ShowLog(string msg)
        {
            if (TextLog.InvokeRequired)
                BeginInvoke(Log, msg);
            else
                Log(msg);
        }
        private void DoClearLog()
        {
            TextLog.Text = "";
        }
        private void ButtonConvert_Click(object sender, System.EventArgs e)
        {
            if (!File.Exists(TextConvertFromFile.Text))
            {
                MessageBox.Show("待转换的文件不存在.", "提示");
                return;
            }
            if (string.IsNullOrEmpty(TextConvertToFile.Text))
            {
                MessageBox.Show("请选择要写出的文件.", "提示");
                return;
            }
            StartConvertThread();
        }
        private void StartConvertThread()
        {
            DoClearLog();
            ConvertStatusChange(true);
            ConvertDelegate d = DoConvert;
            osuStd2KeyConverter c = new osuStd2KeyConverter(TextConvertFromFile.Text, TextConvertToFile.Text);
            c.SetLogDelegate(delegate (string tag, string msg) {
                ShowLog(tag, msg);
            });
            c.SetLogException(delegate (Exception e, string msg)
            {
                msg = "信息:" + (string.IsNullOrEmpty(msg) ? "（无）" : msg) + "\r\n----------------\r\nException:\r\n" + e.ToString();
                ShowLog("Exception", msg);
                MessageBox.Show("转换时发生异常:\r\n"+msg, "转换失败");
            });
            c.SetConvertResultCallback(delegate (bool result, string msg)
            {
                ConvertStatusChange(false);
                
                if (!string.IsNullOrEmpty(msg))
                {
                    ShowLog("Info", msg);
                    MessageBox.Show(msg, result ? "转换成功" : "转换失败");
                }
                else if (result)
                    ShowLog("Info", "转换成功.");
                else
                    ShowLog("Info", "转换失败.");
            });
            d.BeginInvoke(c, null, null);
        }
        private void DoConvert(IConverter c)
        {
            ShowLog("Info", "开始转换.");
            c.Convert();
        }

        private void CheckShowLog_CheckedChanged(object sender, System.EventArgs e)
        {
            if (CheckShowLog.Checked)
                Height += TextLog.Height + 15;
            else
                Height -= TextLog.Height + 15;
        }
    }
}
